/********************************************
 * 功能说明: Message实体对应的业务逻辑Service实现类
 * 模块名称:
 * 系统名称:
 * 软件版权: Frank
 * 系统版本: 1.0.0.1
 * 开发人员: Frank
 * 开发时间: 2019-10-17 18:02:38
 * 审核人员:
 * 相关文档:
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.spring.arch.message.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.spring.arch.message.enums.BusinessType;
import com.spring.arch.message.enums.MessageSendStatus;
import com.spring.arch.message.enums.MessageType;
import com.spring.arch.message.common.sender.sms.SmsResult;
import com.spring.arch.message.common.sender.sms.SmsSender;
import com.spring.arch.message.common.sender.sms.impl.AliSmsSender;
import com.spring.arch.message.enums.BusinessType;
import com.spring.arch.message.enums.MessageSendStatus;
import com.spring.arch.message.enums.MessageType;
import com.spring.arch.message.model.Message;
import com.spring.arch.message.model.SmsTemplateConfig;
import com.spring.arch.message.repository.MessageRepository;
import com.spring.arch.message.repository.SmsTemplateConfigRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.util.UUID;

/**
 * Message实体对应的业务逻辑Service实现类
 *
 * @author Frank
 * @version 1.0.0.1
 * @since 2019-10-17 18:02:38
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class, transactionManager = "masterTransactionManager")
public class MessageService {

    @Autowired
    private SmsSender smsSender;
    @Autowired
    private MessageRepository messageRepository;
    @Autowired
    private SmsTemplateConfigRepository smsTemplateConfigRepository;

    public void save(Message model) {
        this.messageRepository.save(model);
    }

    public void deleteById(UUID id) {
        this.messageRepository.deleteById(id);
    }

    public boolean receptWorkorder(String orderType, String orderCode, String phone) throws ClientException {
        // 取得模板code
        String code = getTemplateCode(BusinessType.WORKORDER_RECEIVE);

        if(StringUtils.isBlank(code)) {
            log.info("业务类型{}的模板code不存在", BusinessType.WORKORDER_RECEIVE);
            return false;
        }

        JSONObject params = new JSONObject();
        params.put("orderType", orderType);
        params.put("orderCode", orderCode);
        SmsResult smsResult = smsSender.sendSms(code, JSON.toJSONString(params), phone);

        if(smsResult.isSuccess()) {

            SendSmsResponse sendSmsResponse = (SendSmsResponse) smsResult.getResult();
            Message message = new Message(phone, BusinessType.WORKORDER_RECEIVE, MessageType.REMINDER,
                    MessageSendStatus.REQUESTSUCCESSFUL);
            message.setBizId(sendSmsResponse.getBizId());
            messageRepository.save(message);

            checkReceptWorkorder(phone, sendSmsResponse.getBizId(), orderType, orderCode);
            return true;
        } else {

            Message message = new Message(phone, BusinessType.WORKORDER_RECEIVE, MessageType.REMINDER,
                    MessageSendStatus.REQUESTFAILURE);
            message.setReason(smsResult.getMsg());
            messageRepository.save(message);
            return false;
        }
    }

    public boolean overtimeWorkorder(String orderType, String orderCode, String orderProcess, String phone) throws ClientException {
        // 取得模板code
        String code = getTemplateCode(BusinessType.WORKORDER_TIMEOUT);

        if(StringUtils.isBlank(code)) {
            log.info("业务类型" + BusinessType.WORKORDER_TIMEOUT + "的模板code不存在");
            return false;
        }
        JSONObject params = new JSONObject();
        params.put("orderType", orderType);
        params.put("orderCode", orderCode);
        params.put("orderProcess", orderProcess);
        SmsResult smsResult = smsSender.sendSms(code, JSON.toJSONString(params), phone);

        if(smsResult.isSuccess()) {

            SendSmsResponse sendSmsResponse = (SendSmsResponse) smsResult.getResult();
            Message message = new Message(phone, BusinessType.WORKORDER_TIMEOUT, MessageType.REMINDER,
                    MessageSendStatus.REQUESTSUCCESSFUL);
            message.setBizId(sendSmsResponse.getBizId());
            messageRepository.save(message);

            checkOvertimeWorkorder(phone, sendSmsResponse.getBizId(), orderType, orderCode, orderProcess);
            return true;
        } else {

            Message message = new Message(phone, BusinessType.WORKORDER_TIMEOUT, MessageType.REMINDER,
                    MessageSendStatus.REQUESTFAILURE);
            message.setReason(smsResult.getMsg());
            messageRepository.save(message);
            return false;
        }
    }

    public boolean followWorkorder(String orderType, String orderCode, String phone) throws ClientException {

        // 取得模板code
        String code = getTemplateCode(BusinessType.WORKORDER_FOUCES);

        if(StringUtils.isBlank(code)) {
            log.info("业务类型" + BusinessType.WORKORDER_FOUCES + "的模板code不存在");
            return false;
        }

        JSONObject params = new JSONObject();
        params.put("orderType", orderType);
        params.put("orderCode", orderCode);
        SmsResult smsResult = smsSender.sendSms(code, JSON.toJSONString(params), phone);

        if(smsResult.isSuccess()) {

            SendSmsResponse sendSmsResponse = (SendSmsResponse) smsResult.getResult();
            Message message = new Message(phone, BusinessType.WORKORDER_FOUCES, MessageType.REMINDER,
                    MessageSendStatus.REQUESTSUCCESSFUL);
            message.setBizId(sendSmsResponse.getBizId());
            messageRepository.save(message);

            checkFollowWorkorder(phone, sendSmsResponse.getBizId(), orderType, orderCode);
            return true;
        } else {

            Message message = new Message(phone, BusinessType.WORKORDER_FOUCES, MessageType.REMINDER,
                    MessageSendStatus.REQUESTFAILURE);
            message.setReason(smsResult.getMsg());
            messageRepository.save(message);
            return false;
        }
    }

    @Async
    void checkOvertimeWorkorder(String phoneNum, String bizId, String orderType, String orderCode,
                                String orderProcess) throws ClientException {
        if(!checkSendResult(phoneNum, bizId)) {
            this.overtimeWorkorder(orderType, orderCode, orderProcess, phoneNum);
        }
    }

    @Async
    void checkReceptWorkorder(String phoneNum, String bizId, String orderType, String orderCode) throws ClientException {
        if(!checkSendResult(phoneNum, bizId)) {
            this.receptWorkorder(orderType, orderCode, phoneNum);
        }
    }

    @Async
    void checkFollowWorkorder(String phoneNum, String bizId, String orderType, String orderCode) throws ClientException {
        if(!checkSendResult(phoneNum, bizId)) {
            this.followWorkorder(orderType, orderCode, phoneNum);
        }
    }

    private boolean checkSendResult(String phoneNum, String bizId) throws ClientException {
        if(smsSender instanceof AliSmsSender) {
            AliSmsSender aliSmsSender = (AliSmsSender) smsSender;
            QuerySendDetailsResponse querySendDetailsResponse = aliSmsSender.querySendDetails(phoneNum, bizId,
                    LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));

            Message message = messageRepository.findByBizId(bizId);
            if("OK".equals(querySendDetailsResponse.getCode())) {
                message.setStatus(MessageSendStatus.SENDSUCCESSFULLY);
                messageRepository.save(message);

                return true;
            } else {
                message.setStatus(MessageSendStatus.SENDFAILURE);
                message.setReason(querySendDetailsResponse.getMessage());
                messageRepository.save(message);
                return false;
            }
        }
        return true;
    }

    /**
     * 根据业务类型获取模板编码
     *
     * @param businessType 业务类型
     * @return 模板编码
     */
    public String getTemplateCode(BusinessType businessType) {
        Optional<SmsTemplateConfig> optional = smsTemplateConfigRepository.findByBusinessType(businessType);
        return optional.map(SmsTemplateConfig :: getTemplateCode).orElse(null);
    }
}
